Skip to content

Fix: Screensaver page and date display#78

Merged
edwardtfn merged 14 commits intomainfrom
v9999.99.9
Mar 30, 2026
Merged

Fix: Screensaver page and date display#78
edwardtfn merged 14 commits intomainfrom
v9999.99.9

Conversation

@edwardtfn
Copy link
Copy Markdown
Owner

@edwardtfn edwardtfn commented Mar 30, 2026

Summary by CodeRabbit

  • New Features

    • Added a customizable screensaver page with persistent background color, text display, and touch wakeup; brightness updates can be delayed for smoother transitions.
  • Bug Fixes

    • Improved datetime and time-provider validation to prevent invalid date/time displays.
    • Fixed screensaver navigation and page-transition behavior.
    • Safer entity lookup in blueprints to avoid missing-data errors.
  • Improvements

    • Reduced watchdog log verbosity.
    • Updated localization sentinel placeholders.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47109af3-8f5d-452c-b83f-07d1d90017af

📥 Commits

Reviewing files that changed from the base of the PR and between 04fc9f3 and 3d9c649.

📒 Files selected for processing (1)
  • esphome/nspanel_esphome_page_weather.yaml

📝 Walkthrough

Walkthrough

Adds guarded screensaver HMI header and empty CPP stub; updates screensaver page scripts (persistent background color, deferred brightness, restart mode), tightens datetime validation/formatting and strftime safety, tweaks display/navigation and watchdog logging, hardens blueprint entity resolution and bumps blueprint/version requirement.

Changes

Cohort / File(s) Summary
Screensaver HMI definitions
components/nspanel_easy/page_screensaver.h, components/nspanel_easy/page_screensaver.cpp
Adds an #ifdef NSPANEL_EASY_PAGE_SCREENSAVER header with HMI component constants (PAGE, TEXT, WAKEUP, SWIPE, TIMER_SWIPESTORE, ALL, COMPONENT_COUNT) and an empty namespaced CPP stub.
Screensaver page logic (ESPhome YAML)
esphome/nspanel_esphome_page_screensaver.yaml
Adds persistent screensaver_background_color, conditional background updates, changes page_screensaver to restart mode, adds page_screensaver_set_brightness_with_wait (5s delay), tightens wakeup/button logic, adjusts page-change execution and sleep scheduling.
Datetime handling
esphome/nspanel_esphome_datetime.yaml
Adds time-provider validity guards, passes actual timestamp to render_date, checks dt validity with distinct warnings, handles unpadded %-d/%-m tokens, and detects strftime "ERROR" sentinel before updating display.
Display & navigation config
esphome/nspanel_esphome_hw_display.yaml
Comments out max_commands_per_loop, uses dynamic get_page_id("home") for back_page_id, and fixes screensaver page-name/timer-reset condition and indentation.
Watchdog logging
esphome/nspanel_esphome_base.yaml
Reduces verbosity of two watchdog round logs from ESP_LOGD to ESP_LOGV.
Localization sentinels
esphome/nspanel_esphome_localization.yaml
Updates sentinel substitutions: __unavailable___{_unavailable_}_, __unknown___{_unknown_}_.
Blueprints / entity resolution
nspanel_easy_blueprint.yaml
Bumps blueprint runtime variables.blueprint_version to 15 and makes entity_id extraction defensive (default trigger.event to {}); filters out empty-string Climate entries.
Version enforcement
esphome/nspanel_esphome_version.yaml
Increments min_blueprint_version substitution from 14 to 15.
Weather page time guard
esphome/nspanel_esphome_page_weather.yaml
Adds time validity check before rendering per-day date and aborts rendering when time is invalid.

Sequence Diagram(s)

sequenceDiagram
    participant Event as PageChange Event
    participant Script as page_screensaver (ESPhome script)
    participant Nextion as Nextion HMI
    participant HW as Hardware Refresh
    participant Time as Time Provider
    participant Bright as Brightness Script

    Event->>Script: enter page == "screensaver"
    Script->>Nextion: set background/foreground/font (if changed)
    Script->>HW: trigger hardware refresh
    Script->>Time: request now (if display_time enabled)
    Time-->>Script: now (valid/invalid)
    alt now valid
        Script->>Nextion: update time text
    else now invalid
        Script-->>Event: log warning, skip time update
    end
    Script->>Bright: start page_screensaver_set_brightness_with_wait (restart)
    Bright->>Bright: wait 5s
    Bright->>Nextion: set brightness
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I stash the black behind a shell so deep,
I wait five beats before the dim lights leap,
I check the clock, refuse to show a lie,
I tidy formats, guards held close and spry —
A hopping rabbit nods: "Screensaver, sleep!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately captures the main focus: fixes to screensaver page functionality and date display handling, which represents the primary changes across multiple configuration and implementation files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v9999.99.9

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
components/nspanel_easy/page_screensaver.h (1)

35-35: Derive the page ID instead of duplicating 9.

pages.h only guarantees that "screensaver" exists. Hard-coding the index here can silently drift if the page table is reordered later.

Suggested change
-constexpr HMIComponent PAGE = {"screensaver", 9};  ///< Screensaver page (index 9 in page_names array)
+constexpr HMIComponent PAGE = {"screensaver", get_page_id("screensaver")};  ///< Screensaver page
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/nspanel_easy/page_screensaver.h` at line 35, PAGE is hard-coded
with ID 9; instead look up the "screensaver" page ID from the canonical pages
table in pages.h at compile or init time rather than duplicating the literal.
Replace the constexpr initialization of PAGE in page_screensaver.h so it derives
its id by calling the existing lookup/mapper (e.g., a constexpr get_page_id or
find_page_index function that takes "screensaver" or by referencing the
page_names/page_table entry) and use that result to construct PAGE; ensure you
reference the exact symbol "screensaver" and the lookup utility from pages.h so
the value follows any reorderings of the page table.
esphome/nspanel_esphome_page_screensaver.yaml (1)

176-190: Let page_screensaver own the sleep brightness update.

page_change -> page_screensaver already applies the sleep brightness immediately and schedules the 5s retry. Line 190 duplicates that write and can dim the current page before the Nextion page change is actually confirmed.

Suggested change
                 ESP_LOGD("${TAG_PAGE_SCREENSAVER}", "Sleep from '%s'", page_names[current_page_id]);
                 goto_page->execute(get_page_id("screensaver"));
-                set_brightness->execute(display_sleep_brightness->state);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@esphome/nspanel_esphome_page_screensaver.yaml` around lines 176 - 190,
Duplicate brightness write: the timer_sleep routine currently calls
set_brightness->execute(display_sleep_brightness->state) which duplicates the
page_change -> page_screensaver behavior and can dim the current page
prematurely; remove the set_brightness->execute(...) call from the timer_sleep
lambda/then block (keep the timeout checks, delay and
goto_page->execute(get_page_id("screensaver")) logic intact) so that
page_screensaver solely owns updating brightness and the 5s retry logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@esphome/nspanel_esphome_datetime.yaml`:
- Around line 154-163: refresh_datetime() currently formats
id(time_provider).now() without checking validity, so invalid clock values can
still be pushed; update refresh_datetime() to call auto now =
id(time_provider).now() and check now.is_valid() (same as render_date()) before
formatting or updating UI, and if invalid log a warning (similar message used in
render_date) and return/skip the update so no invalid time text is rendered.

---

Nitpick comments:
In `@components/nspanel_easy/page_screensaver.h`:
- Line 35: PAGE is hard-coded with ID 9; instead look up the "screensaver" page
ID from the canonical pages table in pages.h at compile or init time rather than
duplicating the literal. Replace the constexpr initialization of PAGE in
page_screensaver.h so it derives its id by calling the existing lookup/mapper
(e.g., a constexpr get_page_id or find_page_index function that takes
"screensaver" or by referencing the page_names/page_table entry) and use that
result to construct PAGE; ensure you reference the exact symbol "screensaver"
and the lookup utility from pages.h so the value follows any reorderings of the
page table.

In `@esphome/nspanel_esphome_page_screensaver.yaml`:
- Around line 176-190: Duplicate brightness write: the timer_sleep routine
currently calls set_brightness->execute(display_sleep_brightness->state) which
duplicates the page_change -> page_screensaver behavior and can dim the current
page prematurely; remove the set_brightness->execute(...) call from the
timer_sleep lambda/then block (keep the timeout checks, delay and
goto_page->execute(get_page_id("screensaver")) logic intact) so that
page_screensaver solely owns updating brightness and the 5s retry logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc8ab32e-2a48-4eec-bade-0e11368a396b

📥 Commits

Reviewing files that changed from the base of the PR and between 31a773a and a4d1b7d.

📒 Files selected for processing (8)
  • components/nspanel_easy/page_screensaver.cpp
  • components/nspanel_easy/page_screensaver.h
  • esphome/nspanel_esphome_base.yaml
  • esphome/nspanel_esphome_datetime.yaml
  • esphome/nspanel_esphome_hw_display.yaml
  • esphome/nspanel_esphome_localization.yaml
  • esphome/nspanel_esphome_page_screensaver.yaml
  • nspanel_easy_blueprint.yaml

Comment thread esphome/nspanel_esphome_datetime.yaml
@edwardtfn edwardtfn changed the title V9999.99.9 Fix: Screensaver page and date display Mar 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
esphome/nspanel_esphome_datetime.yaml (1)

154-167: ⚠️ Potential issue | 🟠 Major

page_weather.yaml passes unsynchronized timestamps without validation.

The page_weather automation at line 79 synthesizes a timestamp from id(time_provider).now().timestamp without checking now.is_valid() first. When passed to render_date->execute(), this timestamp may reconstruct into a spurious 1970-era date if the clock is not yet synchronized, since the render_date function only validates after calling ESPTime::from_epoch_local().

The datetime page's call at line 108 is safe—it guards now.is_valid() much earlier in the same lambda before calling strftime() and before passing the timestamp.

Add an if (!now.is_valid()) return; guard in the page_weather lambda before calculating and passing the synthesized timestamp:

const ESPTime now = id(time_provider).now();
if (!now.is_valid())
  return;
const int32_t seconds_to_noon = (12 - static_cast<int32_t>(now.hour)) * 3600;
const uint32_t timestamp = static_cast<uint32_t>(
    static_cast<int64_t>(now.timestamp) + seconds_to_noon + (page_index * ${SECONDS_PER_DAY}));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@esphome/nspanel_esphome_datetime.yaml` around lines 154 - 167, In the
page_weather lambda that calls id(time_provider).now() and synthesizes a
timestamp to pass to render_date->execute(), add a guard checking now.is_valid()
and return early if false; specifically, after obtaining const ESPTime now =
id(time_provider).now(); insert if (!now.is_valid()) return; before computing
seconds_to_noon, timestamp, or calling render_date->execute(), so you never
build or pass an epoch-derived timestamp from an unsynchronized clock.
🧹 Nitpick comments (2)
components/nspanel_easy/page_screensaver.h (2)

25-32: Minor: Hardcoded page index in documentation.

Line 29 references "index 9 in page_names array" which could become stale if the array order changes. Consider removing the specific index or noting it's determined at compile-time via get_page_id().

That said, the static_assert in pages.h ensures compile-time validation, so this is purely a documentation hygiene concern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/nspanel_easy/page_screensaver.h` around lines 25 - 32, Update the
header comment in page_screensaver.h to remove the hardcoded "index 9 in
page_names array" and instead state that the page index is determined at
compile-time (via get_page_id()) and validated by the static_assert in pages.h;
locate the comment block that mentions "index 9" and replace that phrase with a
neutral description referencing get_page_id() and the static_assert in pages.h
for compile-time validation.

47-50: Clarification: PAGE in ALL[] array.

The comment mentions "All visual components" but PAGE is the page identifier itself rather than a visual component. If this is intentional (e.g., for setting page-level background properties during iteration), the current approach is fine. Otherwise, consider whether ALL[] should only contain {TEXT}.

This is a minor observation and likely by design for your iteration use cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/nspanel_easy/page_screensaver.h` around lines 47 - 50, The ALL[]
array currently contains PAGE and TEXT but PAGE is a page identifier rather than
a visual component; either remove PAGE from ALL so it becomes just {TEXT} and
update COMPONENT_COUNT accordingly (change ALL and recompute sizeof), or if PAGE
must be iterated (e.g., to apply page-level background properties) add a
clarifying comment above ALL explaining why PAGE is included; update the
declaration of ALL and the COMPONENT_COUNT definition (symbols: ALL, PAGE, TEXT,
COMPONENT_COUNT) to reflect the chosen approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@esphome/nspanel_esphome_datetime.yaml`:
- Around line 154-167: In the page_weather lambda that calls
id(time_provider).now() and synthesizes a timestamp to pass to
render_date->execute(), add a guard checking now.is_valid() and return early if
false; specifically, after obtaining const ESPTime now =
id(time_provider).now(); insert if (!now.is_valid()) return; before computing
seconds_to_noon, timestamp, or calling render_date->execute(), so you never
build or pass an epoch-derived timestamp from an unsynchronized clock.

---

Nitpick comments:
In `@components/nspanel_easy/page_screensaver.h`:
- Around line 25-32: Update the header comment in page_screensaver.h to remove
the hardcoded "index 9 in page_names array" and instead state that the page
index is determined at compile-time (via get_page_id()) and validated by the
static_assert in pages.h; locate the comment block that mentions "index 9" and
replace that phrase with a neutral description referencing get_page_id() and the
static_assert in pages.h for compile-time validation.
- Around line 47-50: The ALL[] array currently contains PAGE and TEXT but PAGE
is a page identifier rather than a visual component; either remove PAGE from ALL
so it becomes just {TEXT} and update COMPONENT_COUNT accordingly (change ALL and
recompute sizeof), or if PAGE must be iterated (e.g., to apply page-level
background properties) add a clarifying comment above ALL explaining why PAGE is
included; update the declaration of ALL and the COMPONENT_COUNT definition
(symbols: ALL, PAGE, TEXT, COMPONENT_COUNT) to reflect the chosen approach.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23ad91d2-84a4-4c09-85bb-b189271108ec

📥 Commits

Reviewing files that changed from the base of the PR and between a4d1b7d and 04fc9f3.

📒 Files selected for processing (4)
  • components/nspanel_easy/page_screensaver.h
  • esphome/nspanel_esphome_datetime.yaml
  • esphome/nspanel_esphome_version.yaml
  • nspanel_easy_blueprint.yaml
✅ Files skipped from review due to trivial changes (1)
  • esphome/nspanel_esphome_version.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • nspanel_easy_blueprint.yaml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement ERROR details Bug Screen saver time font size is being lost

1 participant